// Copyright (c) 2005  INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of cgal-python; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; version 2.1 of the License.
// See the file LICENSE.LGPL distributed with cgal-python.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $Id: Py_Triangulation_3.cpp 167 2007-11-02 15:36:54Z spion $
// $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal-python/trunk/cgal-python/bindings/Triangulations_3/Py_Triangulation_3.cpp $
//
// Author(s)     : Naceur Meskini
//=========================================================================


// include ====================================================================
#include <CGAL/basic.h>
#include <include/Kernels.h>

#include <CGAL/Triangulation_3.h>
#include <CGAL/Alpha_shape_vertex_base_3.h>
#include <CGAL/Alpha_shape_cell_base_3.h>
#include <CGAL/Triangulation_vertex_base_with_info_3.h>

#include "Py_Triangulation_3_doc.h"
#include <include/iterator.h>

#include <boost/python.hpp>
#include <boost/cstdint.hpp>
#include <list>


// Using =======================================================================
using namespace boost::python;

namespace  {

	BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(is_valid_overloads_0_2, is_valid, 0, 2)
	BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(is_valid_overloads_1_3, is_valid, 1, 3)
	BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(insert_overloads_1_2, insert, 1, 2)
	BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(locate_overloads_3_4, locate, 3, 4)	
	BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(locate_overloads_1_2, locate, 1, 2)	
	BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(incident_facets_overloads_1_2, incident_facets, 1, 2)	
	BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(incident_vertices_overloads_1_2, incident_vertices, 1, 2)	
	BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(incident_edges_overloads_1_2, incident_edges, 1, 2)	
	BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(triangle_overloads_1_2, triangle, 1, 2)	


}// namespace 

template < class iterator,class Triangulation>
simple_python_iterator<iterator> py_points(Triangulation& tr)
{
	std::pair< iterator , iterator > p( tr.points_begin(), tr.points_end() );
	return simple_python_iterator<iterator>(p);
}
template < class iterator,class Handle,class Triangulation>
Handle_to_py_iterator<iterator,Handle> py_vertices(Triangulation& tr)
{
	std::pair< iterator , iterator > p( tr.finite_vertices_begin(), tr.finite_vertices_end() );
	return Handle_to_py_iterator<iterator,Handle>(p);
}
template < class iterator,class Handle,class Triangulation>
Handle_to_py_iterator<iterator,Handle> py_all_vertices(Triangulation& tr)
{
	std::pair< iterator , iterator > p( tr.all_vertices_begin(), tr.all_vertices_end() );
	return Handle_to_py_iterator<iterator,Handle>(p);
}
template < class iterator,class Triangulation>
simple_python_iterator<iterator> py_facets(Triangulation& tr)
{
	std::pair< iterator , iterator > p( tr.finite_facets_begin(), tr.finite_facets_end() );
	return simple_python_iterator<iterator>(p);
}
template < class iterator,class Triangulation>
simple_python_iterator<iterator> py_all_facets(Triangulation& tr)
{
	std::pair< iterator , iterator > p( tr.all_facets_begin(), tr.all_facets_end() );
	return simple_python_iterator<iterator>(p);
}
template < class iterator,class Triangulation>
simple_python_iterator<iterator> py_edges(Triangulation& tr)
{
	std::pair< iterator , iterator > p( tr.finite_edges_begin(), tr.finite_edges_end() );
	return simple_python_iterator<iterator>(p);
}
template < class iterator,class Triangulation>
simple_python_iterator<iterator> py_all_edges(Triangulation& tr)
{
	std::pair< iterator , iterator > p( tr.all_edges_begin(), tr.all_edges_end() );
	return simple_python_iterator<iterator>(p);
}
template < class iterator,class Handle,class Triangulation>
Handle_to_py_iterator<iterator,Handle> py_cells(Triangulation& tr)
{
	std::pair< iterator , iterator > p( tr.finite_cells_begin(), tr.finite_cells_end() );
	return Handle_to_py_iterator<iterator,Handle>(p);
}
template < class iterator,class Handle,class Triangulation>
Handle_to_py_iterator<iterator,Handle> py_all_cells(Triangulation& tr)
{
	std::pair< iterator , iterator > p( tr.all_cells_begin(), tr.all_cells_end() );
	return Handle_to_py_iterator<iterator,Handle>(p);
}
template < class kernel,class Triangulation>
int py_insert(Triangulation& tr,boost::python::list pts)
{
	typedef typename kernel::Point_3 Point_3;
	int Nb_points = boost::python::extract<int>(pts.attr("__len__")());
	for(int i = 0 ; i < Nb_points ; i++)
	{
		Point_3 P = boost::python::extract<Point_3>(pts[i]); 
		tr.insert(P);
	}
	return Nb_points;
}
template < class Triangulation,class Cell_handle,class Point_3>
Cell_handle py_locate(Triangulation& tri,Point_3 pt,boost::python::list& liste)
{
	Cell_handle result;
	typedef typename Triangulation::Locate_type Locate_type;
	Locate_type lt;
	int li,lj;
	result = tri.locate(pt,lt,li,lj);
	int N = boost::python::extract<int>(liste.attr("__len__")());
	if (N >= 1) for(int i = 0 ; i < N ; i++) liste.remove(liste[0]);
	liste.append(lt);
	liste.append(li);
	liste.append(lj);
	return result;
}
template < class Triangulation,class Cell_handle,class Point_3>
CGAL::Bounded_side py_side_of_cell(Triangulation& tri,Point_3 pt,Cell_handle c,boost::python::list& liste)
{
	CGAL::Bounded_side result;
	typedef typename Triangulation::Locate_type Locate_type;
	Locate_type lt;
	int li,lj;
	result = tri.side_of_cell(pt,c,lt,li,lj);
	int N = boost::python::extract<int>(liste.attr("__len__")());
	if (N >= 1) for(int i = 0 ; i < N ; i++) liste.remove(liste[0]);
	liste.append(lt);
	liste.append(li);
	liste.append(lj);
	return result;
}

template < class Triangulation,class Cell_Or_Facet,class Point_3>
CGAL::Bounded_side py_side_of_facet(Triangulation& tri,Point_3 pt,Cell_Or_Facet c,boost::python::list& liste)
{
	CGAL::Bounded_side result;
	typedef typename Triangulation::Locate_type Locate_type;
	Locate_type lt;
	int li,lj;
	result = tri.side_of_facet(pt,c,lt,li,lj);
	int N = boost::python::extract<int>(liste.attr("__len__")());
	if (N >= 1) for(int i = 0 ; i < N ; i++) liste.remove(liste[0]);
	liste.append(lt);
	liste.append(li);
	liste.append(lj);
	return result;
}

template < class Triangulation,class Cell_Or_Edge,class Point_3>
CGAL::Bounded_side py_side_of_edge(Triangulation& tri,Point_3 pt,Cell_Or_Edge c,boost::python::list& liste)
{
	CGAL::Bounded_side result;
	typedef typename Triangulation::Locate_type Locate_type;
	Locate_type lt;
	int li;
	result = tri.side_of_edge(pt,c,lt,li);
	int N = boost::python::extract<int>(liste.attr("__len__")());
	if (N >= 1) for(int i = 0 ; i < N ; i++) liste.remove(liste[0]);
	liste.append(lt);
	liste.append(li);
	return result;
}

//Face, Edge and Vertex Circulators=====================
template < class Circulator,class Edge,class Triangulation>
simple_python_circulator<Circulator> py_incident_facets(Triangulation& tr,const Edge& e)
{
	Circulator first = tr.incident_facets(e),last;
	std::pair< Circulator , Circulator > p( first, last);
	return simple_python_circulator<Circulator>(p);
}
template < class Circulator,class Cell_handle,class Triangulation>
simple_python_circulator<Circulator> py_incident_facets_2(Triangulation& tr,Cell_handle c,int i,int j)
{
	Circulator first = tr.incident_facets(c,i,j),last;
	std::pair< Circulator , Circulator > p( first, last);
	return simple_python_circulator<Circulator>(p);
}
template < class Circulator,class Edge,class Facet,class Triangulation>
simple_python_circulator<Circulator> py_incident_facets_3(Triangulation& tr,const Edge & e, const Facet & start)
{
	Circulator first = tr.incident_facets(e,start),last;
	std::pair< Circulator , Circulator > p( first, last);
	return simple_python_circulator<Circulator>(p);
}
template < class Circulator,class Cell_handle,class Facet,class Triangulation>
simple_python_circulator<Circulator> py_incident_facets_4(Triangulation& tr,Cell_handle c, int i, int j,const Facet & start)
{
	Circulator first = tr.incident_facets(c,i,j,start),last;
	std::pair< Circulator , Circulator > p( first, last);
	return simple_python_circulator<Circulator>(p);
}
template < class Circulator,class Edge,class Cell_handle,class Triangulation>
simple_python_circulator<Circulator> py_incident_facets_5(Triangulation& tr,const Edge & e,Cell_handle start, int f)
{
	Circulator first = tr.incident_facets(e,start,f),last;
	std::pair< Circulator , Circulator > p( first, last);
	return simple_python_circulator<Circulator>(p);
}
template < class Circulator,class Cell_handle,class Triangulation>
simple_python_circulator<Circulator> py_incident_facets_6(Triangulation& tr,Cell_handle c, int i, int j,Cell_handle start, int f)
{
	Circulator first = tr.incident_facets(c,i,j,start,f),last;
	std::pair< Circulator , Circulator > p( first, last);
	return simple_python_circulator<Circulator>(p);
}

template <class Triangulation>
boost::python::list py_incident_facets_7(Triangulation& tr,typename Triangulation::Vertex_handle v)
{
	boost::python::list result;
	typedef typename Triangulation::Facet  Facet;
	std::list<Facet> liste;
	typename std::list<Facet>::iterator iter;

	tr.incident_facets(v,std::back_inserter(liste));

	for(iter = liste.begin(); iter != liste.end(); iter++)
		result.append(*iter);
	return result;

}
//=============================
//BEGIN========================= incident_cells=============================
template <class Triangulation>
boost::python::list py_incident_cells(Triangulation& tr,typename Triangulation::Vertex_handle v)
{
	boost::python::list result;
	typedef typename Triangulation::Cell_handle  Cell_handle;
	std::list<Cell_handle> liste;
	typename std::list<Cell_handle>::iterator iter;

 	tr.incident_cells(v,std::back_inserter(liste));

	for(iter = liste.begin(); iter != liste.end(); iter++)
		result.append(*iter);
	return result;

}
//========================

template < class Circulator,class Cell_handle,class Edge,class Triangulation>
circulator_to_py_iterator<Circulator,Cell_handle> py_incident_cells_2(Triangulation& tr,const Edge& e)
{
	Circulator first = tr.incident_cells(e),last;
	std::pair< Circulator , Circulator > p( first, last);
	return circulator_to_py_iterator<Circulator,Cell_handle>(p);
}

//=========================
template < class Circulator,class Cell_handle,class Triangulation>
circulator_to_py_iterator<Circulator,Cell_handle> py_incident_cells_3(Triangulation& tr,Cell_handle c,int i,int j)
{
	Circulator first = tr.incident_cells(c,i,j),last;
	std::pair< Circulator , Circulator > p( first, last);
	return circulator_to_py_iterator<Circulator,Cell_handle>(p);
}
//========================

template <class Circulator,class Cell_handle,class Edge,class Triangulation>
circulator_to_py_iterator<Circulator,Cell_handle> py_incident_cells_4(Triangulation& tr,const Edge & e, const Cell_handle & start)
{
	Circulator first = tr.incident_cells(e,start),last;
	std::pair< Circulator , Circulator > p( first, last);
	return circulator_to_py_iterator<Circulator,Cell_handle>(p);
}
//=====================

template < class Circulator,class Cell_handle,class Triangulation>
circulator_to_py_iterator<Circulator,Cell_handle> py_incident_cells_5(Triangulation& tr,Cell_handle c, int i, int j,const Cell_handle& start)
{
	Circulator first = tr.incident_cells(c,i,j,start),last;
	std::pair< Circulator , Circulator > p( first, last);
	return circulator_to_py_iterator<Circulator,Cell_handle>(p);
}
//END========================= incident_cells=============================

//=======================
template < class Circulator,class Vertex_handle,class Triangulation>
simple_python_circulator<Circulator> py_incident_edges(Triangulation& tr,Vertex_handle v)
{
	Circulator first = tr.incident_edges(v),last(NULL);
	std::pair< Circulator , Circulator > p( first, last);
	return simple_python_circulator<Circulator>(p);

}

template <class Triangulation>
boost::python::list py_incident_vertices(const Triangulation& tr,typename Triangulation::Vertex_handle v)
{
	boost::python::list result;
	typedef typename Triangulation::Vertex_handle Vertex_handle;
	std::list<Vertex_handle> liste;
 	typename std::list<Vertex_handle>::iterator iter;
	tr.incident_vertices(v,std::back_inserter(liste));

	for(iter = liste.begin(); iter != liste.end(); iter++)
		result.append(*iter);

	return result;

}

//END Face, Edge and Vertex Circulators=====================

template < class Triangulation>
bool py_is_edge(const Triangulation& tr,typename Triangulation::Vertex_handle u,typename Triangulation::Vertex_handle v, typename Triangulation::Edge& e)
{
	return tr.is_edge(u,v,e.first,e.second,e.third);
}

template < class Triangulation>
bool py_is_facet(const Triangulation& tr,typename Triangulation::Vertex_handle u,typename Triangulation::Vertex_handle v,
 typename Triangulation::Vertex_handle w, typename Triangulation::Cell_handle& c, boost::python::list& l)
{
	int i,j,k;
	bool result = tr.is_facet(u,v,w,c,i,j,k);
	l.append(i);
	l.append(j);
	l.append(k);
	return result;
}
//==========
template < class Triangulation,class Point_3>
typename Triangulation::Vertex_handle py_insert_in_hole(Triangulation& tr,Point_3 pt, const boost::python::list& l, const typename Triangulation::Cell_handle& c,int i)
{
	typedef typename Triangulation::Cell_handle Cell_handle;
	std::list<Cell_handle> list_of_cells;
	int nb_cells = boost::python::extract<int>(l.attr("__len__")());
	for(int j = 0; j < nb_cells ; j++)
		list_of_cells.push_back(boost::python::extract<Cell_handle>(l[j]));

	return tr.insert_in_hole(pt,list_of_cells.begin(),list_of_cells.end(),c,i);
	
}
template < class kernel>
void Py_Triangulation_3()
{
	typedef CGAL::Alpha_shape_vertex_base_3<kernel>         Avb;
	typedef CGAL::Triangulation_vertex_base_with_info_3<boost::python::object,kernel,Avb> 	Vb;

	typedef CGAL::Alpha_shape_cell_base_3<kernel>           Fb;
	typedef CGAL::Triangulation_data_structure_3<Vb,Fb> 	Tds;

	typedef CGAL::Triangulation_3<kernel,Tds>   				Triangulation_3;

	typedef typename Triangulation_3::Facet 					Facet;
	typedef typename Triangulation_3::Finite_facets_iterator 	Finite_facets_iterator;
	typedef typename Triangulation_3::Facet_circulator			Facet_circulator;
	typedef typename Triangulation_3::All_facets_iterator 	    All_facets_iterator;
	typedef typename Triangulation_3::Cell_handle 				Cell_handle;
	typedef typename Triangulation_3::Cell_circulator 			Cell_circulator;
	typedef typename Triangulation_3::All_cells_iterator 		All_cells_iterator;
	typedef typename Triangulation_3::Finite_cells_iterator 	Finite_cells_iterator;

	typedef typename kernel::Point_3 							Point_3;
	typedef typename Triangulation_3::Point_iterator 			Point_iterator;

	typedef typename Triangulation_3::Vertex_handle 			Vertex_handle;
	typedef typename Triangulation_3::Finite_vertices_iterator 	Finite_vertices_iterator;
	typedef typename Triangulation_3::All_vertices_iterator 	All_vertices_iterator;

	typedef typename Triangulation_3::Edge 						Edge;
	typedef typename Triangulation_3::Finite_edges_iterator		Finite_edges_iterator;
	typedef typename Triangulation_3::All_edges_iterator		All_edges_iterator;

	typedef typename Triangulation_3::Locate_type 				Locate_type;
	typedef typename kernel::Segment_3 							Segment_3;
	typedef typename kernel::Triangle_3 						Triangle;

    scope* In_Triangulation_3 = new scope(
    class_< Triangulation_3 >("Triangulation_3",Triangulation_3_doc, init< optional< const kernel& > >())
        .def(init< Triangulation_3& >())
		.def("swap", &Triangulation_3::swap,swap_doc)
		.def("clear", &Triangulation_3::clear,clear_doc)
        .def("dimension", &Triangulation_3::dimension,dimension_doc)
        .def("number_of_cells", &Triangulation_3::number_of_cells,number_of_cells_doc)
        .def("number_of_vertices", &Triangulation_3::number_of_vertices,number_of_vertices_doc)
        .def("infinite_vertex", &Triangulation_3::infinite_vertex,infinite_vertex_doc)
        .def("infinite_cell", &Triangulation_3::infinite_cell,infinite_cell_doc)

        .def("number_of_edges", &Triangulation_3::number_of_edges,number_of_edges_doc)
        .def("number_of_finite_cells", &Triangulation_3::number_of_finite_cells,number_of_finite_cells_doc)
        .def("number_of_finite_facets", &Triangulation_3::number_of_finite_facets,number_of_finite_facets_doc)
        .def("number_of_finite_edges", &Triangulation_3::number_of_finite_edges,number_of_finite_edges_doc)
        .def("tetrahedron", &Triangulation_3::tetrahedron,tetrahedron_doc)

        .def("number_of_facets", &Triangulation_3::number_of_facets,number_of_facets_doc)
        .def("infinite_vertex", &Triangulation_3::infinite_vertex,infinite_vertex_doc)

        .def("is_valid", (bool (Triangulation_3::*)(bool,int) const)&Triangulation_3::is_valid, is_valid_overloads_0_2(is_valid_doc))
        .def("is_valid", (bool (Triangulation_3::*)(Cell_handle,bool,int) const)&Triangulation_3::is_valid, is_valid_overloads_1_3())

       	.def("is_infinite", (bool (Triangulation_3::*)(const Cell_handle) const)&Triangulation_3::is_infinite,is_infinite_doc)
        .def("is_infinite", (bool (Triangulation_3::*)(const Vertex_handle) const)&Triangulation_3::is_infinite)
        .def("is_infinite", (bool (Triangulation_3::*)(const Cell_handle, int) const)&Triangulation_3::is_infinite)
        .def("is_infinite", (bool (Triangulation_3::*)(const Cell_handle, int,int) const)&Triangulation_3::is_infinite)
        .def("is_infinite", (bool (Triangulation_3::*)(const Edge&) const)&Triangulation_3::is_infinite)
        .def("is_infinite", (bool (Triangulation_3::*)(const Facet&) const)&Triangulation_3::is_infinite)
        .def("is_vertex", (bool (Triangulation_3::*)(const Point_3&, Vertex_handle&) const)&Triangulation_3::is_vertex,is_vertex_doc)
        .def("is_vertex", (bool (Triangulation_3::*)(Vertex_handle) const)&Triangulation_3::is_vertex)
        .def("is_edge", py_is_edge<Triangulation_3>,is_edge_doc) 
        .def("is_facet",py_is_facet<Triangulation_3>,is_facet_doc)
        .def("is_cell", (bool (Triangulation_3::*)(Cell_handle) const)&Triangulation_3::is_cell,is_cell_doc)
        .def("is_cell", (bool (Triangulation_3::*)(Vertex_handle,Vertex_handle,Vertex_handle, Vertex_handle,Cell_handle&) const)&Triangulation_3::is_cell) 

        .def("has_vertex", (bool (Triangulation_3::*)(Cell_handle, int,Vertex_handle) const)&Triangulation_3::has_vertex) 
        .def("has_vertex", (bool (Triangulation_3::*)(const Facet&,Vertex_handle) const)&Triangulation_3::has_vertex) 

        .def("are_equal", (bool (Triangulation_3::*)(Cell_handle, int, Cell_handle, int) const)&Triangulation_3::are_equal,are_equal_doc) 
        .def("are_equal", (bool (Triangulation_3::*)(const Facet&, const Facet&) const)&Triangulation_3::are_equal) 
        .def("are_equal", (bool (Triangulation_3::*)(const Facet&,Cell_handle,int) const)&Triangulation_3::are_equal)
 
//         .def("side_of_tetrahedron",&Triangulation_3::side_of_tetrahedron) // to be changed

        .def("triangle", (Triangle (Triangulation_3::*)(const Cell_handle, int)const)&Triangulation_3::triangle,triangle_doc)
        .def("triangle", (Triangle (Triangulation_3::*)(const Facet&)const)&Triangulation_3::triangle)

        .def("segment", (Segment_3 (Triangulation_3::*)(const Cell_handle, int, int) const)&Triangulation_3::segment,segment_doc)
        .def("segment", (Segment_3 (Triangulation_3::*)(const Edge&) const)&Triangulation_3::segment)

        .def("flip", (bool (Triangulation_3::*)(const Facet &))&Triangulation_3::flip,flip_doc)
        .def("flip", (bool (Triangulation_3::*)(const Edge &))&Triangulation_3::flip)
        .def("flip", (bool (Triangulation_3::*)(Cell_handle, int))&Triangulation_3::flip)
        .def("flip", (bool (Triangulation_3::*)(Cell_handle, int,int))&Triangulation_3::flip)
        .def("insert_in_cell",&Triangulation_3::insert_in_cell,insert_in_cell_doc)
        .def("side_of_cell",&py_side_of_cell<Triangulation_3,Cell_handle,Point_3>,side_of_cell_doc)
        .def("side_of_facet",&py_side_of_facet<Triangulation_3,Cell_handle,Point_3>,side_of_facet_doc)
        .def("side_of_facet",&py_side_of_facet<Triangulation_3,Facet,Point_3>,side_of_facet_doc)
        .def("side_of_edge",&py_side_of_edge<Triangulation_3,Cell_handle,Point_3>,side_of_edge_doc)
        .def("side_of_edge",&py_side_of_edge<Triangulation_3,Edge,Point_3>,side_of_edge_doc)

        .def("insert_in_edge",(Vertex_handle (Triangulation_3::*)(const Point_3&,Cell_handle,int,int ))&Triangulation_3::insert_in_edge,insert_in_edge_doc)
        .def("insert_in_edge",(Vertex_handle (Triangulation_3::*)(const Point_3&,const Edge& ))&Triangulation_3::insert_in_edge)

        .def("insert_in_facet",(Vertex_handle (Triangulation_3::*)(const Point_3&,const Facet& ))&Triangulation_3::insert_in_facet)
        .def("insert_in_facet",(Vertex_handle (Triangulation_3::*)(const Point_3&,Cell_handle,int ))&Triangulation_3::insert_in_facet,insert_in_facet_doc)

        .def("insert_outside_convex_hull", &Triangulation_3::insert_outside_convex_hull,insert_outside_convex_hull_doc)
        .def("insert_outside_affine_hull", &Triangulation_3::insert_outside_affine_hull,insert_outside_affine_hull_doc)

        .def("insert", (Vertex_handle (Triangulation_3::*)(const Point_3&, Cell_handle) )&Triangulation_3::insert, insert_overloads_1_2())
        .def("insert", (Vertex_handle (Triangulation_3::*)(const Point_3&, Locate_type, Cell_handle, int,int) )&Triangulation_3::insert)
        .def("insert",&py_insert<kernel,Triangulation_3>,insert_doc)
        .def("insert_in_hole",&py_insert_in_hole<Triangulation_3,Point_3>,insert_in_hole_doc)

		.def("locate", &py_locate<Triangulation_3,Cell_handle,Point_3>,locate_doc)
		.def("locate", (Cell_handle (Triangulation_3::*)(const Point_3&, Cell_handle) const)&Triangulation_3::locate, locate_overloads_1_2())

    	.def("incident_facets", &py_incident_facets<Facet_circulator,Edge,Triangulation_3>,incident_facets_doc)
       	.def("incident_facets", &py_incident_facets_2<Facet_circulator,Cell_handle,Triangulation_3>)
       	.def("incident_facets", &py_incident_facets_3<Facet_circulator,Edge,Facet,Triangulation_3>)
       	.def("incident_facets", &py_incident_facets_4<Facet_circulator,Cell_handle,Facet,Triangulation_3>)
       	.def("incident_facets", &py_incident_facets_5<Facet_circulator,Edge,Cell_handle,Triangulation_3>)
       	.def("incident_facets", &py_incident_facets_6<Facet_circulator,Cell_handle,Triangulation_3>)
       	.def("incident_facets", &py_incident_facets_7<Triangulation_3>)

		.def("incident_vertices", &py_incident_vertices<Triangulation_3>,incident_vertices_doc)

		.def("incident_cells", &py_incident_cells<Triangulation_3>,incident_cells_doc)
		.def("incident_cells", &py_incident_cells_2<Cell_circulator,Cell_handle,Edge,Triangulation_3>)
		.def("incident_cells", &py_incident_cells_3<Cell_circulator,Cell_handle,Triangulation_3>)
		.def("incident_cells", &py_incident_cells_4<Cell_circulator,Cell_handle,Edge,Triangulation_3>)
		.def("incident_cells", &py_incident_cells_5<Cell_circulator,Cell_handle,Triangulation_3>)

		.add_property("facets", &py_facets<Finite_facets_iterator,Triangulation_3>)
		.add_property("vertices", &py_vertices<Finite_vertices_iterator,Vertex_handle,Triangulation_3>/*,vertices_doc*/)
		.add_property("edges", &py_edges<Finite_edges_iterator,Triangulation_3>)
		.add_property("cells", &py_cells<Finite_cells_iterator,Cell_handle,Triangulation_3>)
      	.add_property("points", &py_points<Point_iterator,Triangulation_3>)
        .add_property("all_facets", &py_all_facets<All_facets_iterator,Triangulation_3>)
        .add_property("all_vertices", &py_all_vertices<All_vertices_iterator,Vertex_handle,Triangulation_3>)
        .add_property("all_edges", &py_all_edges<All_edges_iterator,Triangulation_3>)
		.add_property("all_cells", &py_all_cells<All_cells_iterator,Cell_handle,Triangulation_3>)
		.def("degree", &Triangulation_3::degree,degree_doc)
		.def(self==self)
		.def(self!=self)

    );
    enum_< Locate_type >("Locate_type")
        .value("OUTSIDE_CONVEX_HULL", Triangulation_3::OUTSIDE_CONVEX_HULL)
        .value("EDGE", Triangulation_3::EDGE)
        .value("VERTEX", Triangulation_3::VERTEX)
        .value("OUTSIDE_AFFINE_HULL", Triangulation_3::OUTSIDE_AFFINE_HULL)
        .value("FACET", Triangulation_3::FACET)
        .value("CELL", Triangulation_3::CELL)    
	;
    delete In_Triangulation_3;


	Handle_to_py_iterator<Finite_vertices_iterator,Vertex_handle>::declare("Vertex_iterator","is an iterator over a finite vertices");
	Handle_to_py_iterator<Finite_cells_iterator,Cell_handle>::declare("Cell_iterator","is an iterator over a finite cells");
	Handle_to_py_iterator<All_vertices_iterator,Vertex_handle>::declare("All_vertices_iterator","is an iterator over  all vertices");
	Handle_to_py_iterator<All_cells_iterator,Cell_handle>::declare("All_cells_iterator","is an iterator over  all cells");

	simple_python_iterator<Finite_edges_iterator>::declare("Edge_iterator","is an iterator over a finite edges of the triangulation");
	simple_python_iterator<Point_iterator>::declare("Point_iterator","is an iterator over a points of the triangulation");
	simple_python_iterator<Finite_facets_iterator>::declare("Finite_facets_iterator","is an iterator over a finite facets of the triangulation");

	simple_python_iterator<All_facets_iterator>::declare("All_facets_iterator","is an iterator over  all facets of the triangulation");
	simple_python_iterator<All_edges_iterator>::declare("All_edges_iterator","is an iterator over all edges of the triangulation");

	simple_python_circulator<Facet_circulator>::declare("Facet_circulator","is an iterator over a facets of the triangulation\nNo stop iteration.");
	circulator_to_py_iterator<Cell_circulator,Cell_handle>::declare("Cell_circulator","is an iterator over a cells of the triangulation\nNo stop iteration.");

}

void export_Triangulation_3()
{
	Py_Triangulation_3<K>();
}
